/*
 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang.reflect;

import java.security.AccessController;
import sun.reflect.Reflection;
import sun.reflect.ReflectionFactory;
import java.lang.annotation.Annotation;

/**
 * AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。
 * 它提供了将反射对象标记为在使用时抑制默认 Java 语言访问控制检查的能力。
 * 当使用 Field、Method 或 Constructor 来设置或获取字段、调用方法
 * 或创建和初始化类的新实例时，会执行访问检查——
 * 针对 public、default（包）访问、protected 和 private 成员。
 *
 * <p>在反射对象中设置 {@code accessible} 标志允许具有足够权限的复杂应用程序
 * （如 Java 对象序列化或其他持久化机制）以通常被禁止的方式操作对象。
 *
 * <p>默认情况下，反射对象是<em>不</em>可访问的。
 *
 * @see Field
 * @see Method
 * @see Constructor
 * @see ReflectPermission
 *
 * @since 1.2
 */
public class AccessibleObject implements AnnotatedElement {

    /**
     * 用于检查客户端是否具有足够权限来绕过 Java 语言访问控制检查的 Permission 对象。
     */
    static final private java.security.Permission ACCESS_PERMISSION =
        new ReflectPermission("suppressAccessChecks");

    /**
     * 便利方法，通过单次安全检查为对象数组设置 {@code accessible} 标志（为了效率）。
     *
     * <p>首先，如果存在安全管理器，将使用
     * {@code ReflectPermission("suppressAccessChecks")} 权限调用其
     * {@code checkPermission} 方法。
     *
     * <p>如果 {@code flag} 为 {@code true} 但输入 {@code array} 中
     * 任何元素的可访问性不能被更改（例如，如果元素对象是
     * {@link java.lang.Class} 类的 {@link Constructor} 对象），
     * 则抛出 {@code SecurityException}。在发生此类 SecurityException 的情况下，
     * 对象的可访问性将为数组元素设置为 {@code flag}，
     * 直到（但不包括）发生异常的元素；
     * 超出（并包括）发生异常的元素的元素的可访问性保持不变。
     *
     * @param array AccessibleObject 数组
     * @param flag  每个对象中 {@code accessible} 标志的新值
     * @throws SecurityException 如果请求被拒绝。
     * @see SecurityManager#checkPermission
     * @see java.lang.RuntimePermission
     */
    public static void setAccessible(AccessibleObject[] array, boolean flag)
        throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
        for (int i = 0; i < array.length; i++) {
            setAccessible0(array[i], flag);
        }
    }

    /**
     * 将此对象的 {@code accessible} 标志设置为指定的布尔值。
     * {@code true} 值表示反射对象在使用时应抑制 Java 语言访问检查。
     * {@code false} 值表示反射对象应强制执行 Java 语言访问检查。
     *
     * <p>首先，如果存在安全管理器，将使用
     * {@code ReflectPermission("suppressAccessChecks")} 权限调用其
     * {@code checkPermission} 方法。
     *
     * <p>如果 {@code flag} 为 {@code true} 但此对象的可访问性不能被更改
     * （例如，如果此元素对象是 {@link java.lang.Class} 类的
     * {@link Constructor} 对象），则抛出 {@code SecurityException}。
     *
     * <p>如果此对象是 {@code java.lang.Class} 类的
     * {@link java.lang.reflect.Constructor} 对象，
     * 并且 {@code flag} 为 true，则抛出 {@code SecurityException}。
     *
     * @param flag {@code accessible} 标志的新值
     * @throws SecurityException 如果请求被拒绝。
     * @see SecurityManager#checkPermission
     * @see java.lang.RuntimePermission
     */
    public void setAccessible(boolean flag) throws SecurityException {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
        setAccessible0(this, flag);
    }

    /* Check that you aren't exposing java.lang.Class.<init> or sensitive
       fields in java.lang.Class. */
    private static void setAccessible0(AccessibleObject obj, boolean flag)
        throws SecurityException
    {
        if (obj instanceof Constructor && flag == true) {
            Constructor<?> c = (Constructor<?>)obj;
            if (c.getDeclaringClass() == Class.class) {
                throw new SecurityException("Cannot make a java.lang.Class" +
                                            " constructor accessible");
            }
        }
        obj.override = flag;
    }

    /**
     * 获取此对象的 {@code accessible} 标志的值。
     *
     * @return 对象的 {@code accessible} 标志的值
     */
    public boolean isAccessible() {
        return override;
    }

    /**
     * 构造器：仅由 Java 虚拟机使用。
     */
    protected AccessibleObject() {}

    // Indicates whether language-level access checks are overridden
    // by this object. Initializes to "false". This field is used by
    // Field, Method, and Constructor.
    //
    // NOTE: for security purposes, this field must not be visible
    // outside this package.
    boolean override;

    // Reflection factory used by subclasses for creating field,
    // method, and constructor accessors. Note that this is called
    // very early in the bootstrapping process.
    static final ReflectionFactory reflectionFactory =
        AccessController.doPrivileged(
            new sun.reflect.ReflectionFactory.GetReflectionFactoryAction());

    /**
     * 返回此元素上存在的指定类型的注解，如果没有此类型的注解则返回 null。
     *
     * @param <T> 要查询并返回的注解类型（如果存在）
     * @param annotationClass 对应于注解类型的 Class 对象
     * @return 此元素上存在的指定注解类型的注解，如果没有此类型的注解则返回 null
     * @throws NullPointerException 如果给定的注解类为 null
     * @since 1.5
     */
    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        throw new AssertionError("All subclasses should override this method");
    }

    /**
     * 如果指定类型的注解存在于此元素上，则返回 true，否则返回 false。
     * 此方法主要是为了便于访问标记注解而设计的。
     *
     * <p>此方法返回的真值等价于：
     * {@code getAnnotation(annotationClass) != null}
     *
     * <p>默认方法首先调用 {@link #getDeclaredAnnotation(Class)}
     * 传递 {@code annotationClass} 作为参数。如果返回的注解不为 {@code null}，
     * 则返回 {@code true}。否则，如果此注解元素是一个类且传入的注解类型是可继承的，
     * 则默认方法会在此注解元素的超类上递归调用 {@code isAnnotationPresent}。
     *
     * @param annotationClass 对应于注解类型的 Class 对象
     * @return 如果指定注解类型的注解存在于此元素上则返回 true，否则返回 false
     * @throws NullPointerException 如果给定的注解类为 null
     * @since 1.5
     */
    @Override
    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
        return AnnotatedElement.super.isAnnotationPresent(annotationClass);
    }

   /**
     * 返回与此元素关联的指定类型的注解。
     *
     * 如果没有与此元素关联的指定类型的注解，则返回值是一个长度为 0 的数组。
     * 此方法与 {@link #getDeclaredAnnotationsByType(Class)} 的区别在于，
     * 此方法会搜索其超类以查找可继承的注解。
     *
     * @param <T> 要查询并返回的注解类型（如果存在）
     * @param annotationClass 对应于注解类型的 Class 对象
     * @return 与此元素关联的指定类型的所有注解，如果没有关联的注解则返回长度为 0 的数组
     * @throws NullPointerException 如果给定的注解类为 null
     * @since 1.8
     */
    @Override
    public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
        throw new AssertionError("All subclasses should override this method");
    }

    /**
     * 返回此元素上存在的所有注解。
     * 如果此元素没有注解，则返回值是一个长度为 0 的数组。
     * 此方法的调用者可以自由修改返回的数组；这不会对返回给其他调用者的数组产生影响。
     *
     * @return 此元素上存在的所有注解
     * @since 1.5
     */
    public Annotation[] getAnnotations() {
        return getDeclaredAnnotations();
    }

    /**
     * 返回直接存在于此元素上的指定类型的注解，如果没有此类型的注解则返回 null。
     *
     * 此方法忽略继承的注解。（如果没有注解直接存在于此元素上，则返回 null。）
     *
     * @param <T> 要查询并返回的注解类型（如果直接存在）
     * @param annotationClass 对应于注解类型的 Class 对象
     * @return 直接存在于此元素上的指定注解类型的注解，如果没有此类型的注解则返回 null
     * @throws NullPointerException 如果给定的注解类为 null
     * @since 1.8
     */
    @Override
    public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
        // Only annotations on classes are inherited, for all other
        // objects getDeclaredAnnotation is the same as
        // getAnnotation.
        return getAnnotation(annotationClass);
    }

    /**
     * 返回直接存在于此元素上的指定类型的注解。
     *
     * 此方法忽略继承的注解。如果没有指定类型的注解直接存在于此元素上，
     * 则返回值是一个长度为 0 的数组。
     *
     * @param <T> 要查询并返回的注解类型（如果直接存在）
     * @param annotationClass 对应于注解类型的 Class 对象
     * @return 直接存在于此元素上的指定类型的所有注解，如果没有此类型的注解则返回长度为 0 的数组
     * @throws NullPointerException 如果给定的注解类为 null
     * @since 1.8
     */
    @Override
    public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
        // Only annotations on classes are inherited, for all other
        // objects getDeclaredAnnotationsByType is the same as
        // getAnnotationsByType.
        return getAnnotationsByType(annotationClass);
    }

    /**
     * 返回直接存在于此元素上的注解。
     *
     * 此方法忽略继承的注解。如果没有注解直接存在于此元素上，
     * 则返回值是一个长度为 0 的数组。
     * 此方法的调用者可以自由修改返回的数组；这不会对返回给其他调用者的数组产生影响。
     *
     * @return 直接存在于此元素上的注解
     * @since 1.5
     */
    public Annotation[] getDeclaredAnnotations()  {
        throw new AssertionError("All subclasses should override this method");
    }


    // Shared access checking logic.

    // For non-public members or members in package-private classes,
    // it is necessary to perform somewhat expensive security checks.
    // If the security check succeeds for a given class, it will
    // always succeed (it is not affected by the granting or revoking
    // of permissions); we speed up the check in the common case by
    // remembering the last Class for which the check succeeded.
    //
    // The simple security check for Constructor is to see if
    // the caller has already been seen, verified, and cached.
    // (See also Class.newInstance(), which uses a similar method.)
    //
    // A more complicated security check cache is needed for Method and Field
    // The cache can be either null (empty cache), a 2-array of {caller,target},
    // or a caller (with target implicitly equal to this.clazz).
    // In the 2-array case, the target is always different from the clazz.
    volatile Object securityCheckCache;

    void checkAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers)
        throws IllegalAccessException
    {
        if (caller == clazz) {  // quick check
            return;             // ACCESS IS OK
        }
        Object cache = securityCheckCache;  // read volatile
        Class<?> targetClass = clazz;
        if (obj != null
            && Modifier.isProtected(modifiers)
            && ((targetClass = obj.getClass()) != clazz)) {
            // Must match a 2-list of { caller, targetClass }.
            if (cache instanceof Class[]) {
                Class<?>[] cache2 = (Class<?>[]) cache;
                if (cache2[1] == targetClass &&
                    cache2[0] == caller) {
                    return;     // ACCESS IS OK
                }
                // (Test cache[1] first since range check for [1]
                // subsumes range check for [0].)
            }
        } else if (cache == caller) {
            // Non-protected case (or obj.class == this.clazz).
            return;             // ACCESS IS OK
        }

        // If no return, fall through to the slow path.
        slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass);
    }

    // Keep all this slow stuff out of line:
    void slowCheckMemberAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers,
                               Class<?> targetClass)
        throws IllegalAccessException
    {
        Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);

        // Success: Update the cache.
        Object cache = ((targetClass == clazz)
                        ? caller
                        : new Class<?>[] { caller, targetClass });

        // Note:  The two cache elements are not volatile,
        // but they are effectively final.  The Java memory model
        // guarantees that the initializing stores for the cache
        // elements will occur before the volatile write.
        securityCheckCache = cache;         // write volatile
    }
}
